﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using StreetlightGames.SpaceShooter.Patterns;
using System.Reflection;
using System.IO;
using Microsoft.Xna.Framework;
using System.Xml;
using StreetlightGames.XnaEngine;
using StreetlightGames.SpaceShooter.Enemies;

namespace StreetlightGames.SpaceShooter.WaveMetaData
{
    [DataContract]
    public class WaveData
    {
        /// <summary>Gets or sets the Name value</summary>
        [DataMember]
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
        private string _name;

        /// <summary>Gets or sets the IsChallengeStage value</summary>
        [DataMember]
        public bool IsChallengeStage
        {
            get { return _isChallengeStage; }
            set { _isChallengeStage = value; }
        }
        private bool _isChallengeStage;

        /// <summary>Gets or sets the Groups value</summary>
        [DataMember]
        public List<ShipGroup> Groups
        {
            get
            {
                if (_groups == null)
                {
                    _groups = new List<ShipGroup>();
                }
                return _groups;
            }
            set { _groups = value; }
        }
        private List<ShipGroup> _groups;

        /// <summary>Gets or sets the SoundCue value</summary>
        [DataMember]
        public string SoundCue
        {
            get { return _soundCue; }
            set { _soundCue = value; }
        }
        private string _soundCue;
        
        public WaveData()
        {
        }

        public static WaveData CreateDefault()
        {
            WaveData waveData = new WaveData();
            waveData.Name = "Wave 1";
            string beeName = typeof(BeeShip).Name;
            string butterflyName = typeof(ButterflyShip).Name;
            string motherShipName = typeof(MotherShip).Name;
            waveData.Groups.Add(new ShipGroup());
            for (int i = 0; i < 4; i++)
            {
                ShipData ship = new ShipData();
                ship.ShipType = beeName;
                waveData.Groups[0].Ships.Add(ship);
            }
            waveData.Groups.Add(new ShipGroup());
            for (int i = 0; i < 4; i++)
            {
                ShipData ship = new ShipData();
                ship.ShipType = butterflyName;
                waveData.Groups[1].Ships.Add(ship);
            }
            waveData.Groups.Add(new ShipGroup());
            for (int i = 0; i < 4; i++)
            {
                ShipData ship = new ShipData();
                ship.ShipType = motherShipName;
                waveData.Groups[2].Ships.Add(ship);
            }
            waveData.Groups.Add(new ShipGroup());
            for (int i = 0; i < 4; i++)
            {
                ShipData ship = new ShipData();
                ship.ShipType = butterflyName;
                waveData.Groups[3].Ships.Add(ship);
            }
            waveData.Groups.Add(new ShipGroup());
            for (int i = 0; i < 8; i++)
            {
                ShipData ship = new ShipData();
                ship.ShipType = butterflyName;
                waveData.Groups[4].Ships.Add(ship);
            }
            waveData.Groups.Add(new ShipGroup());
            for (int i = 0; i < 8; i++)
            {
                ShipData ship = new ShipData();
                ship.ShipType = beeName;
                waveData.Groups[5].Ships.Add(ship);
            }
            waveData.Groups.Add(new ShipGroup());
            for (int i = 0; i < 8; i++)
            {
                ShipData ship = new ShipData();
                ship.ShipType = beeName;
                waveData.Groups[6].Ships.Add(ship);
            }
            float rad = 300f;
            float shipSpeed = 1000;
            ShipGroup group = waveData.Groups[0];
            group.StartPosition = VectorHelper.ConvertVectorToString(new Vector3(200, 0, -1500));
            group.StartVelocity = VectorHelper.ConvertVectorToString(new Vector3(0, 0, shipSpeed));
            group.AddPattern(new FlyInCircle(rad, -1, MathHelper.PiOver4));
            group.AddPattern(new ContinueForward(500f));
            group.AddPattern(new FlyInCircle(rad, 1, MathHelper.PiOver4 + MathHelper.Pi));
            group.StartDelay = 0;
            group.Interval = 0.2;
            group.AddPattern(new MoveToFormation());
            group.AddPattern(new Hover());
            for (int i = 0; i < 4; i++)
            {
                group.Ships[i].Target = VectorHelper.ConvertVectorToString(new Vector3(-50 + i % 2 * 100, 0, -1000 + 100 * (int)(i / 2)));
            }
            group = waveData.Groups[1];
            group.StartPosition = VectorHelper.ConvertVectorToString(new Vector3(-200, 0, -1500));
            group.StartVelocity = VectorHelper.ConvertVectorToString(new Vector3(0, 0, shipSpeed));
            group.AddPattern(new FlyInCircle(rad, 1, MathHelper.PiOver4));
            group.AddPattern(new ContinueForward(500f));
            group.AddPattern(new FlyInCircle(rad, -1, MathHelper.PiOver4 + MathHelper.Pi));
            group.StartDelay = 0;
            group.Interval = 0.2;
            group.AddPattern(new MoveToFormation());
            group.AddPattern(new Hover());
            for (int i = 0; i < 4; i++)
            {
                ShipData ship = group.Ships[i];
                ship.Target = VectorHelper.ConvertVectorToString(new Vector3(-50 + i % 2 * 100, 0, -1200 + 100 * (int)(i / 2)));
            }
            group = waveData.Groups[2];
            group.StartPosition = VectorHelper.ConvertVectorToString(new Vector3(-800, 0, -200));
            group.StartVelocity = VectorHelper.ConvertVectorToString(new Vector3(shipSpeed, 0, 0));
            group.AddPattern(new ContinueForward(400f));
            group.AddPattern(new FlyInCircle(rad, 1, MathHelper.TwoPi + MathHelper.PiOver2));
            group.AddPattern(new MoveToFormation());
            group.AddPattern(new Hover());
            group.StartDelay = 3;
            group.Interval = 0.4;
            for (int i = 0; i < 4; i++)
            {
                ShipData ship = group.Ships[i];
                ship.Target = VectorHelper.ConvertVectorToString(new Vector3(-150 + 100 * i, 0, -1300));
            }
            group = waveData.Groups[3];
            group.StartPosition = VectorHelper.ConvertVectorToString(new Vector3(-800, 0, -200));
            group.StartVelocity = VectorHelper.ConvertVectorToString(new Vector3(shipSpeed, 0, 0));
            group.AddPattern(new ContinueForward(400f));
            group.AddPattern(new FlyInCircle(rad, 1, MathHelper.TwoPi + MathHelper.PiOver2));
            group.AddPattern(new MoveToFormation());
            group.AddPattern(new Hover());
            group.StartDelay = 3.2;
            group.Interval = 0.4;
            for (int i = 0; i < 4; i++)
            {
                ShipData ship = group.Ships[i];
                ship.Target = VectorHelper.ConvertVectorToString(new Vector3(-150 + i % 2 * 300, 0, -1200 + 100 * (int)(i / 2)));
            }
            group = waveData.Groups[4];
            group.StartPosition = VectorHelper.ConvertVectorToString(new Vector3(800, 0, -200));
            group.StartVelocity = VectorHelper.ConvertVectorToString(new Vector3(-shipSpeed, 0, 0));
            group.AddPattern(new ContinueForward(400f));
            group.AddPattern(new FlyInCircle(rad, -1, MathHelper.TwoPi + MathHelper.PiOver2));
            group.AddPattern(new MoveToFormation());
            group.AddPattern(new Hover());
            group.StartDelay = 8;
            group.Interval = 0.2;
            for (int i = 0; i < 8; i++)
            {
                ShipData ship = group.Ships[i];
                if (i < 4)
                {
                    ship.Target = VectorHelper.ConvertVectorToString(new Vector3(250 + i % 2 * 100, 0, -1200 + 100 * (int)(i / 2)));
                }
                else
                {
                    ship.Target = VectorHelper.ConvertVectorToString(new Vector3(-350 + i % 2 * 100, 0, -1200 + 100 * (int)((i - 4) / 2)));
                }
            }
            group = waveData.Groups[5];
            group.StartPosition = VectorHelper.ConvertVectorToString(new Vector3(200, 0, -1500));
            group.StartVelocity = VectorHelper.ConvertVectorToString(new Vector3(0, 0, shipSpeed));
            group.AddPattern(new FlyInCircle(rad, -1, MathHelper.PiOver4));
            group.AddPattern(new ContinueForward(500f));
            group.AddPattern(new FlyInCircle(rad, 1, MathHelper.PiOver4 + MathHelper.Pi));
            group.AddPattern(new MoveToFormation());
            group.AddPattern(new Hover());
            group.StartDelay = 12;
            group.Interval = 0.2;
            for (int i = 0; i < 8; i++)
            {
                ShipData ship = group.Ships[i];
                if (i < 4)
                {
                    ship.Target = VectorHelper.ConvertVectorToString(new Vector3(150 + i % 2 * 100, 0, -1000 + 100 * (int)(i / 2)));
                }
                else
                {
                    ship.Target = VectorHelper.ConvertVectorToString(new Vector3(-250 + i % 2 * 100, 0, -1000 + 100 * (int)((i - 4) / 2)));
                }
            }
            group = waveData.Groups[6];
            group.StartPosition = VectorHelper.ConvertVectorToString(new Vector3(-200, 0, -1500));
            group.StartVelocity = VectorHelper.ConvertVectorToString(new Vector3(0, 0, shipSpeed));
            group.AddPattern(new FlyInCircle(rad, 1, MathHelper.PiOver4));
            group.AddPattern(new ContinueForward(500f));
            group.AddPattern(new FlyInCircle(rad, -1, MathHelper.PiOver4 + MathHelper.Pi));
            group.AddPattern(new MoveToFormation());
            group.AddPattern(new Hover());
            group.StartDelay = 17;
            group.Interval = 0.2;
            for (int i = 0; i < 8; i++)
            {
                ShipData ship = group.Ships[i];
                if (i < 4)
                {
                    ship.Target = VectorHelper.ConvertVectorToString(new Vector3(-450 + i % 2 * 100, 0, -1000 + 100 * (int)(i / 2)));
                }
                else
                {
                    ship.Target = VectorHelper.ConvertVectorToString(new Vector3(350 + i % 2 * 100, 0, -1000 + 100 * (int)((i - 4) / 2)));
                }
            }
            return waveData;
        }

        public WaveData Duplicate()
        {
            DataContractSerializer serializer = new DataContractSerializer(typeof(WaveData));
            StringBuilder sb = new StringBuilder();
            StringWriter sw = new StringWriter(sb);
            XmlWriter xw = new XmlTextWriter(sw);
            serializer.WriteObject(xw, this);
            StringReader sr = new StringReader(sb.ToString());
            XmlReader xr = new XmlTextReader(sr);
            WaveData waveData = serializer.ReadObject(xr) as WaveData;
            waveData.Name = "Copy of " + Name;
            return waveData;
        }
    }
}
